-
Notifications
You must be signed in to change notification settings - Fork 173
Add Server Streamable Http Transport #235
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Hi @e5l @devcrocod @SeanChinJunKai , would you mind taking a look? |
|
Hi @devcrocod , would you mind taking a look when available? |
6820649 to
465f3dd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @zshea for the PR
Would it be possible to add integration tests to make sure it actually works?
Also, id is mandatory for JSONRPCRequest, JSONRPCResponse, so let's keep it non-nullable
kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types.kt
Outdated
Show resolved
Hide resolved
kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/KtorServer.kt
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried your PR in practice in Stateless mode and brought back what I found.
...commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransport.kt
Outdated
Show resolved
Hide resolved
...commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransport.kt
Outdated
Show resolved
Hide resolved
| block: RoutingContext.() -> Server, | ||
| ) { | ||
| routing { | ||
| post("/mcp") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get requests also need to be processed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't implement because it's not needed for json response. Once we add SSE back, we can do it then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't implement because it's not needed for json response. Once we add SSE back, we can do it then.
https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http
The server MUST either return Content-Type: text/event-stream in response to this HTTP GET, or else return HTTP 405 Method Not Allowed, indicating that the server does not offer an SSE stream at this endpoint
Without processing (which responds with code 405), it seems the inspector was spamming errors.
I replaced post(... with route(".... Everything else has already been implemented by you.
|
Hi @zshea Thanks for this PR. In relation to:
Was an issue created on ktor for this? |
|
One thing that's not clear to me
Looking at the spec the client MUST be able to accept a json response. Is this a bug in the client? From the spec:
|
|
I played around with this a bit.
|
465f3dd to
b01e472
Compare
I found an answer here: https://youtrack.jetbrains.com/issue/KTOR-8327/SSE-Document-how-to-receive-SSE-requests-with-POST-and-other-methods#focus=Comments-27-12594500.0-0 The workaround significantly changes the architectureof how we implement transport: need to split header response and body response. |
TBH I've been struggling with adding tests here, would appreciate some help here, or I can dive more later. Sorry almost forgot this PR for a while... |
Closes #79 #183
Implement server StreamableHttpTransport (both stateful and stateless)
This is a workable solution, tested with Claude Code
Caveat:
enableJsonResponse = true. We can remove this limitation once the upstream has fixed this issue.StreamHttpTransportassumes the SSE stream while the server assumes the JSON response.Motivation and Context
It is painful to support
/sse+/messageendpoint on production. Hopefully we can close this issue with this PR.How Has This Been Tested?
It has been tested in my environment with Claude Code (1.0.89) MCP with both
mcpStreamableHttpandmcpStatelessStreamableHttpBreaking Changes
No, everything is backward compatible
Types of changes
Checklist
Additional context
It is workable with the following implementation:
But the response is always 200, even if we set the status explicitly. And the connection won't be closed with a 4xx or 5xx response. It breaks the MCP spec and can't be used directly. I think we need to create issues to upstream.